﻿/*

Module name "signalR", Service name "hubs".

Use by creating a new instance per specific service hub.
Do not create multiple instances to connect to the same hub.

To enable full error details add this to server hub registration:
RouteTable.Routes.MapHubs(new HubConfiguration { EnableDetailedErrors = true });

Pass to constructor the following params:

hubName - string - name of hub as defined on the server - can be lower case.
options - object - [optional] contains the following options:
    clientFunctions - {fooClient:function(arg1,arg2...) {...},...} - object with callback functions to be called from server.
    defaults - {} - object with properties to be added as default to service scope.
    initialize - function() {...} - function that is called before service is started to allow initialization of properties.
    logging - bool - default false - set to true to log all traffic to console. if false only errors will be logged to console.
*/

angular.module("signalR", [], function () { })
    .factory("hubs", function ($rootScope) {
        var hubs = {};
        return function (hubName, options) {
            options = options || {};
            
            var hubService = hubs[hubName];
            if (hubService) {
                return hubService;
            }
            var hub = $.connection[hubName];
            hubService = $rootScope.$new(true);
            hubs[hubName] = hubService;

            angular.extend(hubService, options.defaults || {});
            
            if (options.initialize) {
                options.initialize.call(hubService);
            }

            angular.extend(hubService, {
                hub: hub,
                client: hub.client,
                server: hub.server
            });

            // Handle calls from server:
            angular.forEach(options.clientFunctions || {}, function (foo, name) {
                hubService[name] = foo;
                hubService.client[name] = function ()
                {
                    if(options.logging)
                    {
                        var $sgrArgs = JSON.stringify(arguments);
                        console.log("SignalR called by server - hub '"+hubName+"' function '"+name+"' args '"+$sgrArgs);
                    }
                    hubService.$apply(
                        foo.apply(hubService, arguments)
                    );
                };
            });

            $.connection.hub.start().done(function () {
                // Handle calls to server:
                angular.forEach(hubService.server,function(foo,name) {
                    hubService[name]= function()
                    {
                        var $sgrArgs = JSON.stringify(arguments);
                        if(options.logging)
                        {
                            console.log("SignalR calling server - hub '" + hubName + "' function '" + name + "' args '" + $sgrArgs);
                        }
                        var res= foo.apply(this,arguments).fail(function(error) {
                            console.log("SignalR Error calling hub '" + hubName + "' function '" + name + "' with args '" + $sgrArgs + "': " + error);
                        });
                        if (options.logging)
                        {
                            res.done(function(result) {
                                var $sgrRes = JSON.stringify(result);
                                console.log("SignalR server response - hub '" + hubName + "' function '" + name + "' args '" + $sgrArgs+" response '"+$sgrRes+"'");
                            });
                        }
                        return res;
                    };
                });
            });
            return hubService;
        };
    });

/*

// Usage Example:
// Defines a service for a hub named "Messages" (server side casing)
// The hub is configured to accept calls and perform callback using method "NewMessage" (server side casing)
// The new service is called 'messages'
// When "NewMessage" is called by server every binding to 'messages.myMessage' will update properly.

angular.module("MyModule", ["signalR"], function() {})
.factory("messages", function (hubs) {
    return hubs("messages", {
        defaults:{myMessage:"no message yet"},
        clientFunctions : {
            newMessage: function (message) {
                this.myMessage = message;
            }
        }
    });
});


*/